import logging
import peewee
from typing import Any, Tuple

from eolcrawl.database.common_db import CommonDB
from eolcrawl.database.spider_db_models import DB, RosRepos
from eolcrawl.spiderutils.common import get_str_md5
from playhouse.shortcuts import model_to_dict  # 添加这行导入
from eolcrawl.spiderutils.log_helper import get_mylogger
from main import spider_map
from typing import Tuple, Dict, Any
from peewee import DoesNotExist

logger = get_mylogger("detailcontent_models",level=logging.INFO)

MAX_GET_NUM = 200


class RosReposDB(CommonDB):
    model = RosRepos

    @classmethod
    @DB.connection_context()
    def get_upload_details(cls, spider_name=None, max_num=MAX_GET_NUM,status=0):
        """
        获取需要上传的detail_content详情信息
        :param spider_name: 爬虫名称，可选
        :param max_num: 最大获取数量
        :return: 详情信息列表，如果发生异常返回空列表
        """
        logger.info("Start querying the database for the list of files that need to be uploaded.")

        try:
            # 查询条件：status = 0
            query = cls.model.select().where(cls.model.status == status).limit(max_num)
            if spider_name:
                query = query.where(cls.model.spider_name == spider_name).limit(max_num)

            results = list(query)
            logger.info(f"get details Number is = {len(results)}")

            # 输出结果（仅在 DEBUG 模式下执行）
            if logger.isEnabledFor(logging.DEBUG):
                for result in results:
                    logger.debug(f"{result._id}, {result.title}")

            # 转换为字典
            return [result.to_dict() for result in results]
    
        except Exception as e:
            logger.exception(f"Failed to get upload details: {e}")
            return None

    @classmethod
    @DB.connection_context()
    def update_status(cls, _id, spider_name, status=1) -> Tuple[bool, str, int]:
        """更新状态
        
        Args:
            _id (str): 标题ID
            spider_name (str): 爬虫名称
            status: 状态更新status，默认为1
            
        Returns:
            Tuple[bool, str, int]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - int: 更新的记录数，0表示没有记录被更新
        """
        try:
            query = cls.model.update(status=status).where(
                (cls.model.spider_name == spider_name) & 
                (cls.model._id == _id)
            )
            result = query.execute()
            return True, "更新成功" if result > 0 else "没有记录被更新", result
        except Exception as e:
            error_msg = f"更新状态失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, 0

    #更新status状态,根据spider_name和status
    @classmethod
    @DB.connection_context()
    def update_status_by_spider_name(cls, spider_name, q_status,status):
        try:
            query = cls.model.update(status=status).where(cls.model.spider_name == spider_name).where(cls.model.status == q_status)
            result = query.execute()
            return True, "更新成功" if result > 0 else "没有记录被更新",    result
        except Exception as e:
            error_msg = f"更新状态失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, 0

    @classmethod
    @DB.connection_context()
    def get_detail_content(cls, _id, spider_name):
        """
        获取详情内容
        :param id: 标题ID
        :param spider_name: 爬虫名称
        :return: 查询结果字典
        """
        try:
            query = cls.model.select().where(cls.model._id == _id)
            if not query.exists():
                return None
            return query.dicts()
        except Exception as e:
            logger.exception(f"Failed to get detail content: {e}")
            return None

    @classmethod
    @DB.connection_context()
    def get_detail_content_by_id(cls, id):
        """
        根据ID获取详情内容
        :param id: 记录ID
        :return: 查询结果字典
        """
        try:
            query = cls.model.select().where(cls.model._id == id)
            if not query.exists():
                return None
            return query.dicts()
        except Exception as e:
            logger.exception(f"Failed to get detail content by id: {e}")
            return None
    
    @classmethod
    @DB.connection_context()
    def insert_detail_content(cls, data) -> Tuple[bool, str, Any]:
        """插入详情内容
        
        Args:
            data: 可以是字典或 DetailContent 实例
            
        Returns:
            Tuple[bool, str, Any]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - Any: 成功时返回新记录的ID，失败时返回None
        """
        try:
            # 如果是 DetailContent 实例，转换为字典
            if isinstance(data, cls.model):
                insert_data = model_to_dict(data)
            else:
                insert_data = data
            
            result = cls.model.insert(insert_data).execute()
            return True, "插入成功", result
        except Exception as e:
            error_msg = f"插入详情内容失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, None
    
    @classmethod
    @DB.connection_context()
    def insert_detail_content_batch(cls, data) -> Tuple[bool, str, int]:
        """批量插入详情内容
        
        Args:
            data (list): 要插入的数据列表
            
        Returns:
            Tuple[bool, str, int]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - int: 插入的记录数，0表示没有记录被插入
        """
        try:
            result = cls.model.insert_many(data).execute()
            return True, "批量插入成功", result
        except Exception as e:
            error_msg = f"批量插入详情内容失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, 0
        
    @classmethod
    @DB.connection_context()
    def insert_or_update_detail_content(cls, data) -> Tuple[bool, str, Any]:
        """插入或更新详情内容
        
        Args:
            data (dict): 要插入或更新的数据字典
            
        Returns:
            Tuple[bool, str, Any]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - Any: 成功时返回新记录的ID，失败时返回None
        """
        try:
            result = cls.model.insert(data).on_conflict_ignore().execute()
            return True, "插入或更新成功", result
        except Exception as e:
            error_msg = f"插入或更新详情内容失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, None
    
    @classmethod
    @DB.connection_context()
    def update_detail_content(cls, data) -> Tuple[bool, str, int]:
        """更新详情内容
        
        Args:
            data (dict): 要更新的数据字典
            
        Returns:
            Tuple[bool, str, int]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - int: 更新的记录数，0表示没有记录被更新
        """
        try:
            result = cls.model.update(data).execute()
            return True, "更新成功" if result > 0 else "没有记录被更新", result
        except Exception as e:
            error_msg = f"更新详情内容失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, 0
        
    @classmethod
    @DB.connection_context()
    def update_detail_contentByCondition(cls, data: Dict[str, Any], condition: Any) -> Tuple[bool, str, int]:
        """
        更新详情内容

        Args:
            data (Dict[str, Any]): 要更新的数据字典，键为字段名，值为字段值。
            condition (Any): 更新条件，用于指定哪些记录需要被更新。

        Returns:
            Tuple[bool, str, int]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - int: 更新的记录数，0表示没有记录被更新
        """
        try:
            # 如果传入的是模型实例，转换为字典
            if isinstance(data, cls.model):
                update_data = model_to_dict(data)
            else:
                update_data = data

            # 移除None值的字段，避免覆盖已有数据
            update_data = {k: v for k, v in update_data.items() if v is not None and v != ''}

            # 执行更新操作
            result = cls.model.update(update_data).where(condition).execute()

            if result > 0:
                return True, "更新成功", result
            else:
                return True, "没有记录被更新", result

        except DoesNotExist:
            error_msg = "更新条件未匹配到任何记录"
            logger.warning(error_msg)
            return False, error_msg, 0

        except Exception as e:
            error_msg = f"更新详情内容失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, 0
    
    #save_detail_content
    @classmethod
    def save_detail_content(cls,data):
        """
        保存详情内容
        """
        try:
            result = cls.model.save(data)
            return True, "save成功", result
        except Exception as e:
            error_msg = f"save详情内容失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, None
    @classmethod
    @DB.connection_context()
    def update_partial(cls, instance_id: str, update_fields: Dict[str, Any]) -> Tuple[bool, str, Any]:
        """
        更新指定记录的部分字段
        
        Args:
            instance_id: 记录ID
            update_fields: 要更新的字段字典，如 {'field1': 'value1', 'field2': 'value2'}
            
        Returns:
            Tuple[bool, str, Any]: (是否成功, 消息, 结果)
        """
        try:
            # 获取记录实例
            record = cls.model.get(cls.model._id == instance_id)
            
            # 更新指定字段
            for field, value in update_fields.items():
                setattr(record, field, value)
                
            # 只保存更新的字段
            result = record.save(only=list(update_fields.keys()))
            return True, "部分更新成功", result
        except cls.model.DoesNotExist:
            return False, f"记录不存在: {instance_id}", None
        except Exception as e:
            error_msg = f"部分更新失败: {str(e)}"
            logger.exception(error_msg)
            return False, error_msg, None
    @classmethod
    def build_detail_instert_data(cls,item,name):
        """
        构建插入数据的元组
        :param item: 包含数据的字典
        :param name: spider 名称
        :return: 插入数据的元组
        """
        def get_text_value(item,arg):
            return item[arg] if arg in item else ""
        
        def get_list_value(item,arg):
            return ", ".join(item[arg]) if arg in item and isinstance(item[arg], list) else ""
    
        detail_content = RosRepos()
        detail_content._id = get_str_md5(item["name"])
        detail_content.spider_name = name
        detail_content.url = get_text_value(item,"url")
        detail_content.name = get_text_value(item,"name")
        detail_content.branch = get_text_value(item,"branch")
        detail_content.ros_pkg_name = detail_content.name.split(detail_content.branch)[1]+'-' if detail_content.name else ""
        detail_content.src_name = get_text_value(item,"src_name")
        detail_content.src_url = get_text_value(item,"src_url")
        detail_content.src_version = get_text_value(item,"src_version")
        detail_content.src_size = get_text_value(item,"src_size")
        detail_content.src_release_date = get_text_value(item,"src_release_date")
        detail_content.status = -1

        logger.debug(f"detail_content: {detail_content}")

        # 构建数据元组
        return detail_content

    @classmethod
    def build_realsecode_instert_data(cls,item,name):
        """
        构建插入数据的元组
        :param item: 包含数据的字典
        :param name: spider 名称
        :return: 插入数据的元组
        """
        def get_text_value(item,arg):
            return item[arg] if arg in item else ""
        
        def get_list_value(item,arg):
            return ", ".join(item[arg]) if arg in item and isinstance(item[arg], list) else ""
    
        detail_content = RosRepos()
        if name == "agiros_realse_code":
            # detail_content._id = get_str_md5(item["name"])
            detail_content.release_src_name =get_text_value(item,"name")
            detail_content.release_src_url = get_text_value(item,"url")
            detail_content.status = 2
            print(f"id :{detail_content._id} name:{detail_content.release_src_name}  url:{detail_content.release_src_url}")
 
        elif name  == "agiros_realse_pkg":
            # detail_content._id = get_str_md5(item["name"])
            detail_content.release_pkg_name = get_text_value(item,"org_pkg_name")
            detail_content.release_pkg_url = get_text_value(item,"url")
            detail_content.release_pkg_version = get_text_value(item,"version")
            detail_content.status = 3
        else:
            logger.error(f"covert item to db data failed,items:{item}")

        logger.debug(f"detail_content: {detail_content}")

        # 构建数据元组
        return detail_content

    @classmethod
    def build_realsecode_update_data(cls,existing_record,item,name):
        def get_text_value(item,arg):
            return item[arg] if arg in item else ""
        
        if name == "agiros_realse_code":
            # detail_content._id = get_str_md5(item["name"])
            existing_record.release_src_name =get_text_value(item,"name")
            existing_record.release_src_url = get_text_value(item,"url")
            existing_record.status = 2
            print(f"id :{existing_record._id} name:{existing_record.release_src_name}  url:{existing_record.release_src_url}")
 
        elif name  == "agiros_realse_pkg":
            # detail_content._id = get_str_md5(item["name"])
            existing_record.release_pkg_name = get_text_value(item,"org_pkg_name")
            existing_record.release_pkg_url = get_text_value(item,"url")
            existing_record.release_pkg_version = get_text_value(item,"version")
            existing_record.status = 3
        else:
            logger.error(f"covert item to db data failed,items:{item}")

        logger.debug(f"detail_content: {existing_record}")
        return existing_record

        
# 主程序
if __name__ == '__main__':
    
    # 示例调用
    # details = get_upload_details("bjjwdetail")
    # update_status("e6f6a81771a34b3e84157d50ab12c3e6","bjjwdetail",300)
    # logger.info(f"detail_content main start ================================= test =================================")
    pass



